package com.nsn.mib.trap.parser;

import java.io.BufferedWriter;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import edu.stanford.nlp.ling.HasWord;
import edu.stanford.nlp.ling.IndexedWord;
import edu.stanford.nlp.process.DocumentPreprocessor;
import edu.stanford.nlp.process.WordToSentenceProcessor;
import edu.stanford.nlp.semgraph.SemanticGraph;
import edu.stanford.nlp.semgraph.SemanticGraphEdge;
import edu.stanford.nlp.trees.GrammaticalRelation;
import edu.stanford.nlp.trees.TypedDependency;

public class ParserUtil {
	
	public static final int THREHOLD_OF_WORDCOUNT = 10;
	public static final int MIN_OF_WORDCOUNT = 2;

	public static String[] DEL_RELATIONS = {"conj"};

	public static int MAXDEEP = 5;
	
	public static String[] DELETE_WORS_TAGS = {/*"DT","WRB"*/};
	
	public static LinkedList<String> TRAP_NAME_PATTERNS = new LinkedList<String>(){
		/**
		 * 
		 */
		private static final long serialVersionUID = 1L;
		{
			add("notification");
			add("trap");
			add("event");
			add("notify");
			add("alarm");
		}
	};

	public static String[] FIRST_HOP_RELATIONS = {"nsubj","nsubjpass","rcmod"};
	
	public static String[] NEXT_RELATIONS = {"advcl","ccomp","prep","dobj","parataxis","dep","xcomp","rcmod"};
	
	public static String[] COMPLETED_RELATIONS = {"nsubj","nsubjpass","dobj","cop"};
	
	public static void alterPatterns(String temp)
	{
		TRAP_NAME_PATTERNS.add(temp);
	}
	
	public static void recoverPatterns()
	{
		TRAP_NAME_PATTERNS.removeLast();
	}
	
	public static String replaceSpecificWord(String src)
	{
		if(src.contains("-LRB-"))
			return "(";
		if(src.contains("-RRB-"))
			return ")";
		return src;
	}
	
	public static String postProcess(String src)
	{
		return null;
	}
	
	public static List<GrammaticalRelation> array2Collection(String[] relns)
	{
		List<GrammaticalRelation> rels = new ArrayList<GrammaticalRelation>();
		
		for(String s : relns)
		{
			rels.add(GrammaticalRelation.valueOf(s));
		}
		return rels;
	}
	
	public static boolean save2File(String src,String dst)
	{
		List<AlarmObject> alarms = readXml(src);
		try {
			ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream(dst));
			for(AlarmObject ao : alarms)
			{
				os.writeObject(ao);
			}
			os.close();
			
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		}  
		return true;
	}
	
	/*Read All AlarmObjects  From XML*/
	public static List<AlarmObject> readXml(String src)
	{
		StanfordParser sdPaser = StanfordParser.getInstance();
		List<AlarmObject> alarms = new LinkedList<AlarmObject>();
		try 
		{
			int count = 0;
			SAXReader dr = new SAXReader();
		
			Document d = dr.read(new File(src));
			
			Element root = d.getRootElement();
			
			for(Iterator i = root.elementIterator(); i.hasNext(); ) 
			{
			      Element element = (Element) i.next();
			      String name = element.elementText("NAME");
			      String description = element.elementText("DESC");
			      
			      description = ParserUtil.deleteBlank(description);
			      
			      List<TypedDependency> deps = sdPaser.DPFromString(description);
			      
			      alarms.add(new AlarmObject(name,description,null,deps));
			      
			      count++;
			      System.out.println("done:" + count);
			      
			}
			
		} catch (DocumentException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				return null;
		}
		return alarms; 
	}
	
	@SuppressWarnings("finally")
	public static List<AlarmObject> readDataFile(String src) throws FileNotFoundException, IOException
	{
		List<AlarmObject> alarms = new LinkedList<AlarmObject>();
		ObjectInputStream oi = new ObjectInputStream(new FileInputStream(src));
		try 
		{
			while(true)
			{
				alarms.add((AlarmObject) oi.readObject());
			}
			
		} catch(EOFException e)
		{
			return alarms;
		} 
		finally
		{
			oi.close();
			return alarms;
		}
	}
	
	public static List<GrammaticalRelation> getClauseRelations()
	{
		List<GrammaticalRelation> l = new LinkedList<GrammaticalRelation>();
		for(String s : NEXT_RELATIONS)
		{
			l.add(GrammaticalRelation.valueOf(s));
		}
		return l;
	}
	
	
	public static String deleteBlank(String src)
	{
		Pattern p = Pattern.compile("\\s{1,}");
		Matcher m = p.matcher(src);
		return m.replaceAll(" ").trim();
	}
	
	public static String firstSentences(String src)
	{
		String[] array =  src.split("\\.");
		for(int i = 0;i < array.length;i++)
		{
			if(array[i] != null && array[i] != "")
			{
				return array[i];
			}
		}
		return null;
	}
	
	public static String preprocess(String src)
	{
		String[] array =  src.split("\\.");
		for(int i = 0;i < array.length;i++)
		{
			if(array[i] != null && array[i] != "")
			{
				for(String s:ParserUtil.TRAP_NAME_PATTERNS)
				if(array[i].contains(s))
				{
					return array[i];
				}
			}
		}
			
		return firstSentences(src);
	}
	
	public static boolean hasMatchSentence(String src)
	{
		List<String> sents = new LinkedList<String>();
		String[] array =  src.split("\\.");
		for(int i = 0;i < array.length;i++)
		{
			if(array[i] != null && array[i] != "")
			{
				for(String s:ParserUtil.TRAP_NAME_PATTERNS)
				if(array[i].contains(s))
				{
					return true;
				}
			}
		}
		
		return false;
	}
	
	public static List<String> splitSentens(String src)
	{
		List<String> sents = new LinkedList<String>();
		String[] array =  src.split("\\.");
		for(int i = 0;i < array.length;i++)
		{
			if(array[i] != null && array[i] != "")
			{
				for(String s:ParserUtil.TRAP_NAME_PATTERNS)
				if(array[i].contains(s))
				{
					sents.add(array[i]);
				}
			}
		}
		
		if(sents.isEmpty())
		{
			sents.add(firstSentences(src));
		}
		
		return sents;
	}
	
	public static boolean canParse(String src)
	{
		try 
		{
			File temp = File.createTempFile("temp", ".txt");
			temp.deleteOnExit();
			
			BufferedWriter out = new BufferedWriter(new FileWriter(temp));
	        out.write(src);
	        out.close();
	        
	        DocumentPreprocessor dp = new  DocumentPreprocessor(new InputStreamReader(new FileInputStream(temp)));
	        WordToSentenceProcessor<HasWord> sp  = new WordToSentenceProcessor<HasWord>(true);
	        
	        List<List<HasWord>> sentences = new ArrayList<List<HasWord>>();
	        for (List<HasWord> sentence : dp)
	        {
	        	sentences.add(sentence);
	        }
	        
	        if(sentences.size() == 1)
	        {
	        	if(sentences.get(0).size() <= 10)
	        	{
	        		return true;
	        	}
	        }
	    
	        
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		}
		
		return false;
	}
	
	public static void addTreeElement(Element root,SemanticGraph sg)
	{
		Element tree = root.addElement("TREE");
		Collection<IndexedWord> roots = sg.getRoots();
		for(IndexedWord child : roots)
		{
			Element childRoot = tree.addElement("ROOT");
			childRoot.addAttribute("word", child.originalText());
			childRoot.addAttribute("index", String.valueOf(child.index()));
			childRoot.addAttribute("tag",child.tag());
			
			if(sg.hasChildren(child))
			{
				buildTree(childRoot,child,sg);
			}
		}
	}

	private static void buildTree(Element tree, IndexedWord child,
			SemanticGraph sg) {
		// TODO Auto-generated method stub
	
		//System.out.println(child.originalText());
		List<SemanticGraphEdge> es = sg.getOutEdgesSorted(child);
		if(es != null && es.size() > 0)
		{
			for(SemanticGraphEdge e : es)
			{
				Element childRoot = tree.addElement(e.getRelation().getShortName());
				IndexedWord dep = e.getDependent();
				childRoot.addAttribute("word", dep.originalText());
				childRoot.addAttribute("index", String.valueOf(dep.index()));
				childRoot.addAttribute("tag",dep.tag());
				
				if(sg.hasChildren(dep))
				{
					//SemanticGraphEdge t =  sg.getEdge(child, dep);
					//List<Pair<GrammaticalRelation, IndexedWord>>ps = sg.childPairs(dep);
					if(dep.index() != child.index())
					{
						buildTree(childRoot,dep,sg);
					}
				}
			}
		}
	}
	
	/*
	  	try {
			System.setOut(new PrintStream("jnx.xml"));
			System.out.println("<TRAPS>");
			for(Trap t : traps)
			{
				
				System.out.println("<TRAP>");
				System.out.println("<NAME>");
				System.out.println(t.getName());
				System.out.println("</NAME>");
				System.out.println("<DESC>");
				System.out.println(t.getDesciption().trim());
				System.out.println("</DESC>");
				System.out.println("</TRAP>");
				
			}
			System.out.println("</TRAPS>");
		} catch (FileNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	 */
}